/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import ts from '../vendor/ohos-typescript';

export function isCamelCase(str: string): boolean {
    return /^[a-z]+([A-Z][a-z]*)*$/.test(str);
}

export function isPascalCase(str: string): boolean {
    return /^[A-Z][a-z]*([A-Z][a-z]*)*$/.test(str);
}

export function countCharactersAndNewlines(sourceFile: ts.SourceFile, child: ts.Node, nameConcent: ts.Node, openParenToken: ts.Node): [charCount: number, newlineCount: number] {
  // 确保范围有效
  const startIndex = sourceFile.getLineAndCharacterOfPosition(nameConcent.getEnd()); // 获取 nameConcent 的结束位置
  const endIndex = sourceFile.getLineAndCharacterOfPosition(openParenToken.getStart()); // 获取 openParenToken 的开始位置
  const newlineCount = endIndex.line - startIndex.line;
  const nameConcentText = nameConcent.getText();
  const fullText = child.getText();
  const startdex = fullText.lastIndexOf(nameConcentText) + nameConcentText.length;
  let charCount = 0;
  if (newlineCount > 0) {
    charCount = newlineCount + endIndex.character;
  } else {
    charCount = endIndex.character - startIndex.character;
  }
  // 统计字符数和换行符数
  const subString = fullText.substring(startdex, startdex + charCount).replace('?', '').replace('.', '');
  return [subString.length, newlineCount];
}

export function getNextToken(token: ts.Node | undefined, sourceFile: ts.SourceFile): ts.Node | undefined {
  if (!token) { return undefined };
  const scanner = ts.createScanner(ts.ScriptTarget.Latest, false, ts.LanguageVariant.Standard, sourceFile.getFullText());
  scanner.setTextPos(token.end);
  while (true) {
    const tokenSyntaxKind = scanner.scan();
    if (tokenSyntaxKind === ts.SyntaxKind.EndOfFileToken) { break };

    const nextTokenStart = scanner.getTokenPos();
    const nextTokenEnd = scanner.getTextPos();
    const nextTokenText = sourceFile.text.substring(nextTokenStart, nextTokenEnd);

    if (!/\s/.test(nextTokenText) && !isComment(nextTokenText)) {
      return findNodeAtPosition(sourceFile, nextTokenStart, nextTokenEnd);
    }
  }
  return undefined;
}

export function findNodeAtPosition(sourceFile: ts.SourceFile, start: number, end: number): ts.Node | undefined {
  let result: ts.Node | undefined = undefined;
  ts.forEachChild(sourceFile, node => {
    if (node.pos <= start && node.end >= end) {
      result = node;
    }
  });
  return result;
}

export function isComment(text: string): boolean {
  return /\/\*[\s\S]*?\*\/|\/\/.*/.test(text);
}

export function hasControlCharacters(pattern: string): boolean {
  // \t & 0x00~0x1F
  const regex = /\\x[0-1][0-9A-Fa-f]|\\u00[0-1][0-9A-Fa-f]|\\u\{[A-Fa-f]{1,2}\}|\t/g;
  return regex.test(pattern);
}

export function getFileExtension(filePath: string, filetype: string): boolean {
    const match = filePath.match(/\.([0-9a-zA-Z]+)$/);
    if (match) {
        const extension = match[1];
        return extension === filetype;
    }
    return false;
};

export function getParenPosition(node: ts.FunctionLikeDeclaration): number | null {
    const openParen = node.getChildren().find(c => c.kind === ts.SyntaxKind.OpenParenToken);
    return openParen?.getStart() || null;
}

export function findClosingAngleBracket(code: string, startPos: number): number {
    let pos = startPos;
    while (pos < code.length) {
        if (code[pos] === '>') {
            return pos;
        }
        pos++;
    }
    return -1;
}

export function findClosingAngleBracketForMethod(code: string, startPos: number): number {
    let pos = startPos;
    let stack = 1; // 初始栈为1，匹配外层泛型
    while (pos < code.length) {
        const char = code[pos];
        if (char === '<') {
            stack++;
        } else if (char === '>') {
            stack--;
            if (stack === 0) {
                return pos; // 返回最外层闭合的 '>'
            }
        }
        pos++;
    }
    return -1;
}

